/**
 * 
 */
package com.nervytech.tutorcruise.spring.controller;

import java.util.Date;
import java.util.LinkedList;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.nervytech.tutorcruise.application.util.IConstants;
import com.nervytech.tutorcruise.application.util.UUIDGenerator;
import com.nervytech.tutorcruise.db.dao.model.User;
import com.nervytech.tutorcruise.db.dao.model.UserUuid;
import com.nervytech.tutorcruise.db.enums.MessageTypeEnum;
import com.nervytech.tutorcruise.db.enums.UserStatusEnum;
import com.nervytech.tutorcruise.db.enums.UserTypeEnum;
import com.nervytech.tutorcruise.db.enums.UuidTypeEnum;
import com.nervytech.tutorcruise.db.service.interfaces.IStateService;
import com.nervytech.tutorcruise.db.service.interfaces.IUserService;
import com.nervytech.tutorcruise.db.service.interfaces.IUserUuidService;
import com.nervytech.tutorcruise.message.service.EmailSender;
import com.nervytech.tutorcruise.spring.common.form.LoginForm;
import com.nervytech.tutorcruise.spring.common.form.RegistrationForm;
import com.nervytech.tutorcruise.spring.form.validator.RegistrationValidator;

/**
 * @author ADMIN
 * 
 */

@Controller
@RequestMapping("/reg/join")
public class RegistrationController {

	private static final Logger logger = LoggerFactory
			.getLogger(RegistrationController.class);

	@Autowired
	private RegistrationValidator registrationValidator;

	@Autowired
	private IUserService userService;

	@Autowired
	private UserDetailsService userDetailsService;

	@Autowired
	private PasswordEncoder passwordEncoder;

	@Autowired
	private SaltSource saltSource;

	@Autowired
	private IStateService stateService;

	@Autowired
	private IUserUuidService usrUuidService;

	private Map<String, String> cityMap;

	@ModelAttribute("cityMap")
	public Map<String, String> populateCityMap() {
		// cityMap = cityDAO.getCityMap();
		return cityMap;
	}

	@RequestMapping(method = RequestMethod.GET)
	public String showForm(Map model) {

		RegistrationForm regForm = new RegistrationForm();
		regForm.setFrmOrigin("register");
		
		model.put("registrationForm", regForm);

		return "register";
	}

	@Transactional
	@RequestMapping(method = RequestMethod.POST)
	public String registerUser(RegistrationForm regForm, BindingResult result,
			Map model, HttpServletRequest request) {
		
		registrationValidator.validate(regForm, result);

		if (result.hasErrors()) {

			if (regForm.getFrmOrigin().equals("home")) {
				return "home";
			} else {
				return "register";
			}
		}

		User usr = null;

		try {

			boolean isUserExist = userService.checkIfUserExist(regForm
					.getEmailId());

			if (isUserExist) {

				result.rejectValue("emailId",
						"NotEmpty.registrationForm.emailId",
						"Please enter a valid email Id.");

				regForm.setMessage("This email address already exists in our system!");
				regForm.setMessageType(MessageTypeEnum.ERROR.toString());

				if (regForm.getFrmOrigin().equals("home")) {
					return "home";
				} else {
					return "register";
				}
			}
			
			Date currentDate = new Date();

			usr = new User();
			usr.setCreatedTime(currentDate);
			usr.setEmail(regForm.getEmailId().toLowerCase());
			usr.setFullName(regForm.getFullName());
			usr.setPassword(regForm.getPassword());
			usr.setUpdatedTime(currentDate);
			// usr.setCity(regForm.getCity());
			usr.setZipCode(regForm.getZipCode());
			usr.setUserType(UserTypeEnum.DEFAULT.getType()); // Setting to
																// default
			usr.setUserStatus(UserStatusEnum.CREATED.getStatus());

			userService.saveUser(usr);
			
			// Update encrypted password ........
			UserDetails userDetails = userDetailsService
					.loadUserByUsername(usr.getEmail());

			usr.setPassword(passwordEncoder.encodePassword(
					regForm.getPassword(), saltSource.getSalt(userDetails)));

			userService.updatePassword(usr.getUserId(), usr.getPassword());

			UserUuid usrUuid = new UserUuid();
			usrUuid.setUuid(UUIDGenerator.getTimeUUID().toString());
			usrUuid.setUserId(usr.getUserId());
			usrUuid.setType(UuidTypeEnum.REGCONFIRM.getType());
			usrUuid.setCreatedTime(new Date());

			usrUuidService.saveUuid(usrUuid);

			String confirmationUrl = request.getRequestURL().toString()
					+ "/confirm/email/" + regForm.getEmailId() + "/id/"
					+ usr.getUserId() + "/hash/" + usrUuid.getUuid();

			logger.info("ConfirmationUrl for user : " + regForm.getEmailId()
					+ " is " + confirmationUrl);

			sendConfirmationMail(regForm, confirmationUrl);
			
			String fromOrigin = regForm.getFrmOrigin();

			regForm = new RegistrationForm();

			regForm.setEmailId(regForm.getEmailId());
			regForm.setMessage("An activation mail has been sent to your registered email Id. "
					+ "Please follow the mail to activate your account.");
			regForm.setMessageType(MessageTypeEnum.SUCCESS.name());

			model.put("registrationForm", regForm);

			if (fromOrigin.equals("home")) {
				return "home";
			} else {
				return "register";
			}

		} catch (Exception e) {

			logger.error("Unable to register", e);
			
			String fromOrigin = regForm.getFrmOrigin();

			regForm = new RegistrationForm();

			regForm.setEmailId(regForm.getEmailId());
			regForm.setMessage("Unable to register. Please contact support at "
					+ IConstants.SUPPORT_EMAIL);
			regForm.setMessageType(MessageTypeEnum.ERROR.name());
			regForm.setFrmOrigin(fromOrigin);
			
			model.put("registrationForm", regForm);
			
			if (fromOrigin.equals("home")) {
				return "home";
			} else {
				return "register";
			}

		}
	}

	@RequestMapping(value = "/confirm/email/{emailId}/id/{usrId}/hash/{uuId}", method = RequestMethod.GET)
	public String confirmUser(@PathVariable String emailId,
			@PathVariable String usrId, @PathVariable String uuId, Map model) {

		try {

			UserUuid usrUuid = new UserUuid();
			usrUuid.setUuid(uuId);
			usrUuid.setUserId(Long.parseLong(usrId));
			usrUuid.setType(UuidTypeEnum.REGCONFIRM.getType());

			boolean isValid = usrUuidService.isValidUuid(usrUuid, emailId);

			if (isValid) {

				User usr = new User();
				usr.setUserStatus(UserStatusEnum.ENABLED.getStatus());
				usr.setUpdatedTime(new Date());

				userService.updateStatus(Long.parseLong(usrId),
						usr.getUserStatus());

				usrUuidService.deleteUuid(uuId);
			} else {
				RegistrationForm regForm = new RegistrationForm();
				regForm.setMessage("Oops !!! Your request can not be completed. Please check the request or contact our support at "
						+ IConstants.SUPPORT_EMAIL);
				regForm.setMessageType(MessageTypeEnum.ERROR.name());

				model.put("registrationForm", regForm);

				return "home";
			}

			LoginForm loginForm = new LoginForm();
			loginForm.setMessage("Successfully activated. You can login now.");
			loginForm.setMessageType(MessageTypeEnum.SUCCESS.name());

			model.put("loginForm", loginForm);

			return "login";

		} catch (Exception e) {

			logger.info("Invalid user id " + usrId);

			RegistrationForm regForm = new RegistrationForm();
			regForm.setMessage("Oops !!! Your request can not be completed. Please check the request or contact our support at "
					+ IConstants.SUPPORT_EMAIL);
			regForm.setMessageType(MessageTypeEnum.ERROR.name());

			model.put("registrationForm", regForm);

			return "home";

		}

	}

	private void sendConfirmationMail(RegistrationForm regForm,
			String confirmationUrl) {
		String content = "Hi "
				+ regForm.getFullName()
				+ ","
				+ "\n Please click the following link for activating your account.\n "
				+ confirmationUrl;

		logger.debug("Sending registration confirmation mail : user "
				+ regForm.getEmailId());

		try {
			LinkedList<String> recipientsList = new LinkedList<String>();
			recipientsList.add(regForm.getEmailId().trim());
			// AmazonEmailSender.sendTextMail(Constants.CONFIRMATION_MAIL_FROM,
			// recipientsList, Constants.CONFIRMATION_MAIL_SUBJECT, content);
			EmailSender.sendMail("<gmail_id>", regForm.getEmailId(), "Confirmmmm", content);

			logger.debug("Confirmation mail was successfully sent to the user "
					+ regForm.getEmailId());
		} catch (Exception e) {
			logger.warn("Unable to send the Confirmation mail to the user "
					+ regForm.getEmailId() + " Confirmation URL is "
					+ confirmationUrl);
			logger.error("Unable to send Confirmation Mail to the user "
					+ regForm.getEmailId() + " .", e);
		}
	}

}
